#include "DataStorage.h"
#include "EEPROM.h"
#include <Arduino.h>
#include "log.h"


#define DATA_STORAGE_PWM_S5_HEADER_SIZE 0x40

#define DATA_STORAGE_PWM_S5_REG_SIZE 87

#define DATA_STORAGE_PWM_S5_GENERAL_INFO_SIZE 20

#define DATA_STORAGE_STATUS_NUM 4

#define DATA_STORAGE_EOF 0x55AA

#define DATA_STORAGE_STATUS_ADDRESS_OFFSET (DATA_STORAGE_PWM_S5_HEADER_SIZE)

#define DATA_STORAGE_STATUS0_START_ADDRESS (int)(0x00+DATA_STORAGE_STATUS_ADDRESS_OFFSET)
#define DATA_STORAGE_STATUS1_START_ADDRESS (int)(DATA_STORAGE_STATUS0_START_ADDRESS+DATA_STORAGE_PWM_S5_GENERAL_INFO_SIZE)
#define DATA_STORAGE_STATUS2_START_ADDRESS (int)(DATA_STORAGE_STATUS1_START_ADDRESS+DATA_STORAGE_PWM_S5_GENERAL_INFO_SIZE)
#define DATA_STORAGE_STATUS3_START_ADDRESS (int)(DATA_STORAGE_STATUS2_START_ADDRESS+DATA_STORAGE_PWM_S5_GENERAL_INFO_SIZE)


#define DATA_STORAGE_STATUS_EOF_ADDRESS   (int)(DATA_STORAGE_PWM_S5_REG_SIZE+DATA_STORAGE_STATUS_ADDRESS_OFFSET)

DataStorage::DataStorage(Mail<>& mb):_mb(mb)
{

}
DataStorage::~DataStorage()
{

}
void DataStorage::begin()
{
    EEPROM.begin();
    //make_default();
    if(this->load()){
        log::debug("read eeprom:ok\r\n");
    }else{
        make_default();
        log::debug("make default:ok\r\n");
    }
}
void DataStorage::make_default()
{
    //生成头部信息
    module_header_reg().module_number.value      = 0x0002;
    module_header_reg().hardware_version         = 0x01;
    module_header_reg().software_version         = 0x01;
    module_header_reg().module_type              = 1;
    module_header_reg().protocol_part_1.value    = 0x87;
    module_header_reg().protocol_part_2.value    = 0x01;
    strcpy((char*)&module_header_reg().module_name[0],"WF1-PWM_S5");
    
    //写入头部信息到EEPROM
    for(uint8_t i=0;i<data_storage_header_size();i++){
        EEPROM.write(i,module_header_reg().data[i]); 
    }
 
    //生成寄存器默认配置
    module_general_reg_t& module_general_reg = DataStorage::module_reg().module_general_reg;
    module_general_reg.module_control_reg.value = 0;
    module_general_reg.module_reserved_43_reg.value = 0;
    module_general_reg.module_status_number_reg.value = 0;
    module_general_reg.module_actived_status_reg.value = 1;
    module_general_reg.module_reserved_46_reg.value = 0;
    module_general_reg.module_pin_level_reg.value = 0;
    for(uint8_t i=0;i<DATA_STORAGE_STATUS_NUM;i++){
        module_general_reg.module_general_info[i].freq_mode_select_status_reg.value            = 0;
        module_general_reg.module_general_info[i].freq_mode_select_status_reg.smfn_m           = 1;

        module_general_reg.module_general_info[i].pin_used_reg.value                           = 0x1F;
        module_general_reg.module_general_info[i].pin_output_mode_reg.value                    = 0x1F;

        module_general_reg.module_general_info[i].pwm_duty_cycle_reg.red_pin.value             = 50;
        module_general_reg.module_general_info[i].pwm_duty_cycle_reg.green_pin.value           = 60;
        module_general_reg.module_general_info[i].pwm_duty_cycle_reg.blue_pin.value            = 70;
        module_general_reg.module_general_info[i].pwm_duty_cycle_reg.white_pin.value           = 80;
        module_general_reg.module_general_info[i].pwm_duty_cycle_reg.yellow_pin.value          = 90;

        module_general_reg.module_general_info[i].pwm_custom_freq_reg.red_pin.value               = 1000;
        module_general_reg.module_general_info[i].pwm_custom_freq_reg.green_pin.value             = 1000;
        module_general_reg.module_general_info[i].pwm_custom_freq_reg.blue_pin.value              = 1000;
    }
    //写入默认配置到EEPROM
    for(int i=(DATA_STORAGE_STATUS_ADDRESS_OFFSET);i<(DATA_STORAGE_PWM_S5_REG_SIZE+DATA_STORAGE_STATUS_ADDRESS_OFFSET);i++){
        EEPROM.write(i,module_general_reg.data[i-DATA_STORAGE_STATUS_ADDRESS_OFFSET]);
    }
    //写入0x55AA激活配置
    EEPROM.write(DATA_STORAGE_STATUS_EOF_ADDRESS,0xAA);
    EEPROM.write(DATA_STORAGE_STATUS_EOF_ADDRESS+1,0x55);
    
}

bool DataStorage::load()
{
    if(this->read_data_storage_eof() != DATA_STORAGE_EOF){
        return false;
    }
    for(uint32_t i=0;i<data_storage_header_size();i++){
        module_header_reg().data[i] = EEPROM.read(i);
    }

    for(uint32_t i=(DATA_STORAGE_STATUS_ADDRESS_OFFSET);i<(DATA_STORAGE_STATUS_ADDRESS_OFFSET+DATA_STORAGE_PWM_S5_REG_SIZE);i++){
        module_reg().module_general_reg.data[i-DATA_STORAGE_STATUS_ADDRESS_OFFSET] = EEPROM.read(i);
    }
    return true;
}   

int DataStorage::read_data_storage_eof()
{
    int eof_address=DATA_STORAGE_STATUS_EOF_ADDRESS;
    _data_storage_eof._AA = EEPROM.read(eof_address);
    _data_storage_eof._55 = EEPROM.read(eof_address+1);
    return _data_storage_eof.value;
}

void DataStorage::check_update()
{   
    //检查头部寄存器
    bool _update = false;

    for(uint32_t i=0;i<data_storage_header_size();i++){
        if(!_mb.empty()){
            return;
        }
        if(EEPROM.read(i) !=  module_header_reg().data[i]){
            _update = true;
            break;
        }
    }

    if(_update){
        for(uint32_t i=0;i<data_storage_header_size();i++){
            if(!_mb.empty()){
                return;
            }
            EEPROM.write(i, module_header_reg().data[i]);
        }
        //log::debug("update eeprom header:%s\r\n",_update?"Y":"N");
    }

    //检查通用寄存器
    _update = false;

    for(uint32_t _check_index=DATA_STORAGE_STATUS_ADDRESS_OFFSET;_check_index<(DATA_STORAGE_STATUS_ADDRESS_OFFSET+DATA_STORAGE_PWM_S5_REG_SIZE);_check_index++){
        if(!_mb.empty()){
            return;
        }
        module_general_reg_t& module_general_reg = DataStorage::module_reg().module_general_reg;
        if(EEPROM.read(_check_index) != module_general_reg.data[_check_index-DATA_STORAGE_STATUS_ADDRESS_OFFSET]){
            _update = true;
            break;
        }
    }

    if(_update){
        //写入默认配置到EEPROM
        for(int i=(DATA_STORAGE_STATUS_ADDRESS_OFFSET);i<(DATA_STORAGE_PWM_S5_REG_SIZE+DATA_STORAGE_STATUS_ADDRESS_OFFSET);i++){
            if(!_mb.empty()){
                return;
            }
            module_general_reg_t& module_general_reg = DataStorage::module_reg().module_general_reg;
            EEPROM.write(i,module_general_reg.data[i-DATA_STORAGE_STATUS_ADDRESS_OFFSET]);
        }
        log::debug("update eeprom reg:%s\r\n",_update?"Y":"N");
    }

    
}

data_storage_reg_read_t& DataStorage::get_reg_data(uint8_t reg_address)
{
    module_general_reg_t& module_general_reg = module_reg().module_general_reg;
    switch (reg_address)
    {
        case 0x00:
        case 0x01:
        {
            _reg_read.data    = module_header_reg().module_number.data;
            _reg_read.size    = sizeof(module_header_reg().module_number.data);
        }
        break;
        case 0x02:
        {
            _reg_read.data    = module_header_reg().hardware_version_data;
            _reg_read.size    = sizeof(module_header_reg().hardware_version_data);
        }
        break;
        case 0x03:
        {
            _reg_read.data    = module_header_reg().software_version_data;
            _reg_read.size    = sizeof(module_header_reg().software_version_data);
        }
        break;
        case 0x04:
        {
            _reg_read.data    = module_header_reg().module_type_data;
            _reg_read.size    = sizeof(module_header_reg().module_type_data);
        }
        break;
        case 0x05:
        case 0x06:
        {
            _reg_read.data    = module_header_reg().protocol_data;
            _reg_read.size    = sizeof(module_header_reg().protocol_data);
        }
        break;
        case 0x07:
        {
            _reg_read.data    = module_header_reg().module_name;
            _reg_read.size    = 10;
            //_reg_read.size    = sizeof(module_header_reg().module_name);
        }
        break;
        case 0x42:
        {
            _reg_read.data = module_general_reg.module_control_reg.data;
            _reg_read.size    = sizeof(module_general_reg.module_control_reg.data);
        }
        break;
    case 0x44:
        {
            _reg_read.data    = module_general_reg.module_status_number_reg.data;
            _reg_read.size    = sizeof(module_general_reg.module_status_number_reg.data);
        }
        break;
    case 0x45:
        {
            _reg_read.data     = module_general_reg.module_actived_status_reg.data;
            _reg_read.size     = sizeof(module_general_reg.module_actived_status_reg.data);
        }
        break;
    
    case 0x46:break;
    case 0x47:
    {   
        _reg_read.data     = module_general_reg.module_pin_level_reg.data;
        _reg_read.size     = sizeof(module_general_reg.module_pin_level_reg.data);
        log::debug("0x47->read:%d\r\n",_reg_read.data);
    }   
    break;
    case 0x48:
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].freq_mode_select_status_reg.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].freq_mode_select_status_reg.data);
        }
        break;
    case 0x49:
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pin_used_reg.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pin_used_reg.data);
        }
        break;
    case 0x4A:
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pin_output_mode_reg.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pin_output_mode_reg.data);
            log::debug("4a->read:%d\r\n",_reg_read.data[0]);
        }
        break;
    case 0x4B:// R 引脚占空比
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_duty_cycle_reg.red_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_duty_cycle_reg.red_pin.data);
        }
        break;
    case 0x4C:// G 引脚占空比
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_duty_cycle_reg.green_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_duty_cycle_reg.green_pin.data);
        }
        break;
    case 0x4D:// B 引脚占空比
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_duty_cycle_reg.blue_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_duty_cycle_reg.blue_pin.data);
        }
        break;
    case 0x4E:// W 引脚占空比
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_duty_cycle_reg.white_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_duty_cycle_reg.white_pin.data);
        }
        break;
    case 0x4F:// Y 引脚占空比
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_duty_cycle_reg.yellow_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_duty_cycle_reg.yellow_pin.data);
        }
        break;
    case 0x50:// R 频率
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.red_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.red_pin.data);
        }
        break;
    case 0x51:// R 频率
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.red_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.red_pin.data);
        }
        break;
    case 0x52:// R 频率
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.red_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.red_pin.data);
        }
        break;
    case 0x53:// R 频率
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.red_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.red_pin.data);
        }
        break;
    case 0x54:// G 频率
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.green_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.green_pin.data);
        }
        break;
    case 0x55:// G 频率
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.green_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.green_pin.data);
        }
        break;
    case 0x56:// G 频率
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.green_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.green_pin.data);
        }
        break;
    case 0x57:// G 频率
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.green_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.green_pin.data);
        }
        break;
    case 0x58:// B 频率
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.blue_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.blue_pin.data);
        }
        break;
    case 0x59:// B 频率
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.blue_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.blue_pin.data);
        } 
        break;
    case 0x5A:// B 频率
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.blue_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.blue_pin.data);
        }
        break;
    case 0x5B:// B 频率
        {
            _reg_read.data     = module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.blue_pin.data;
            _reg_read.size     = sizeof(module_general_reg.module_general_info[module_general_reg.module_status_number_reg.value].pwm_custom_freq_reg.blue_pin.data);
        }
        break;
    default:
        {
            _reg_read.data    = (uint8_t*)"NG";
            _reg_read.size    = 2;
        }
        break;
    }


    return _reg_read;
}
